﻿using HDF5DotNet;
using MathNet.Numerics.Data.Matlab;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.Charts;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using OpenCvSharp;
using satellite_helper.Class;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;

namespace satellite_helper
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        int start = 0;
        public double[,] public_readData_to_byte;
        private static int myFunction(H5GroupId id, string objectName, object param)
        {
            Console.WriteLine("The object name is {0}", objectName);
            Console.WriteLine("The object parameter is {0}", param);
            return 0;
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {

        }
        //打开目录
        private void open_directory_click(object sender, RoutedEventArgs e)
        {

        }
        //打开文件
        private void open_file_click(object sender, RoutedEventArgs e)
        {

        }

        private void Button_Click_read(object sender, RoutedEventArgs e)
        {
            //定义文件路径
            string filename = "111.h5";
            //新建dataset
            GetHdf5DataSet getData = new GetHdf5DataSet();
            //获取目录数组
            string[] groupNames = getData.hdf5_getData(filename);
            //只读模式打开
            H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDWR);
            //取其中某一目录
            H5DataSetId dataSetId = H5D.open(fileId, groupNames[0]);
            //获取目录的spaceid
            H5DataSpaceId h5DataSpaceId = H5D.getSpace(dataSetId);
            //查询目录在h5位置
            int rank = H5S.getSimpleExtentNDims(h5DataSpaceId);
            //查询目录矩阵大小
            long[] a = H5S.getSimpleExtentDims(h5DataSpaceId);
            //建立对应大数组
            double[,] readDataBack = new double[a[0], a[1]];
            //目录数据存入内存
            H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE), new H5Array<double>(readDataBack));
        }

        private void Button_Click_write(object sender, RoutedEventArgs e)
        {
            string fime_name = "new_write.h5";
            H5FileId fileId = H5F.create(fime_name, H5F.CreateMode.ACC_TRUNC);
            long[] dims = new long[1];
            dims[0] = 10;

            //一维数据准备
            int[] data_one_demo = new int[10];
            for (int i = 0; i < 10; i++)
            {
                data_one_demo[i] = i;
            }

            //二维数据准备
            int[,] data_two_demo = new int[10, 10];
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    data_two_demo[i, j] = i * j;
                }
            }

            //三维数据准备
            int[,,] data_three_demo = new int[10, 10, 10];
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        data_three_demo[i, j, k] = i * j * k;
                    }
                }
            }

            H5DataSpaceId spaceId = H5S.create_simple(1, dims);
            H5DataTypeId typeId = H5T.copy(H5T.H5Type.NATIVE_INT);

            // 获取数据类型占用空间
            int typeSize = H5T.getSize(typeId);

            //不知道干啥的两句,注释了似乎也没影响
            H5T.setOrder(typeId, H5T.Order.BE);
            H5T.setOrder(typeId, H5T.Order.LE);

            // 创建h5一维数据块
            H5DataSetId dataSetId = H5D.create(fileId, "/data_01", typeId, spaceId);
            // 创建h5二维数据块
            H5DataSetId dataSetId_two_demo = H5D.create(fileId, "/data_02", typeId, H5S.create_simple(2, new long[2] { 10, 10 }));
            // 创建h5三维数据块
            H5DataSetId dataSetId_three_demo = H5D.create(fileId, "/data_03", typeId, H5S.create_simple(3, new long[3] { 10, 10, 10 }));

            // 一维写入
            H5D.write(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT), new H5Array<int>(data_one_demo));

            // 二维写入
            H5D.write(dataSetId_two_demo, new H5DataTypeId(H5T.H5Type.NATIVE_INT), new H5Array<int>(data_two_demo));

            // 三维写入
            H5D.write(dataSetId_three_demo, new H5DataTypeId(H5T.H5Type.NATIVE_INT), new H5Array<int>(data_three_demo));

            //必须关闭全部句柄
            H5D.close(dataSetId);
            H5D.close(dataSetId_two_demo);
            H5D.close(dataSetId_three_demo);
            H5S.close(spaceId);
            H5T.close(typeId);
            H5F.close(fileId);

            //带初始种子的随机写入
            //int singleValue = 999999;
            //H5D.writeScalar(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_INT),ref singleValue);
        }

        private void Button_Click_mat_read(object sender, RoutedEventArgs e)
        {
            //Matrix<double> m = MatlabReader.Read<double>(@"E:\RamanSpectrum_graduation\PeakSearching\PeakSearching\bin\Debug\yuanshuju.mat");//读取MATLAB中的数据，

            Matrix<double> m2334455 = MatlabReader.Read<double>("1.mat");
            Array testArray = m2334455.ToArray();
            double[] data = new double[testArray.Length];
            int j = 0;
            foreach (double GG in testArray)
            {
                data[j] = GG;
                j++;
            }
        }

        private void Button_Click_mat_write(object sender, RoutedEventArgs e)
        {
            //数据准备
            double[,] data_two_demo = new double[10, 10];
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    data_two_demo[i, j] = i * j;
                }
            }
            Matrix<double> m = DenseMatrix.OfArray(data_two_demo);
            //注意，完成此操作后，如果要解决内存占用问题，可以提前释放_listData和arr的内存占用
            using (FileStream fs = new FileStream($"1.mat", FileMode.Create))
            {
                //特别注意保存文件时的内存占用问题
                MatlabWriter.Write(fs, m, "export");
            };
        }

        private void one_demo_draw(object sender, RoutedEventArgs e)
        {
            double[] x = new double[100];
            double[] y = new double[100];
            for (int i = 0; i < 100; i++)
            {
                x[i] = i;
                y[i] = 100 - i;
            }
            EnumerableDataSource<double> xDataSource = x.AsXDataSource();
            EnumerableDataSource<double> yDataSource = y.AsYDataSource();
            CompositeDataSource compositeDataSource = xDataSource.Join(yDataSource);
            LineGraph lineGraph = new LineGraph(compositeDataSource);
            Legend.SetDescription(lineGraph, "测试曲线");
            // < d3:ChartPlotter Name = "plotter" Margin = "10,10,10,10" Height = "200" />
            ChartPlotter plotter = new ChartPlotter
            {
                Margin = new Thickness(10, 10, 10, 10),
                Height = 200
            };
            windows_middle.Children.Add(plotter);
            plotter.Children.Add(lineGraph);
            plotter.FitToView();
        }

        private void two_demo_draw(object sender, RoutedEventArgs e)
        {
            int img_width = 2048;
            int img_height = 4096;
            byte[] bytes = new byte[img_width * img_height];
            int k = 0;
            for (int i = 0; i < img_width; i++)
            {
                for (int j = 0; j < img_height; j++)
                {
                    bytes[k++] = (byte)(i + j);
                }
            }
            Bitmap bmp = ToGrayBitmap(bytes, img_width, img_height);

            //bmp.Save(@"d:\test.png",System.Drawing.Imaging.ImageFormat.Png);
            IntPtr ip = bmp.GetHbitmap();//从GDI+ Bitmap创建GDI位图对象

            BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

            System.Windows.Controls.Image image = new System.Windows.Controls.Image
            {
                Width = img_width,
                Height = img_height,
                Name = "imgOutput",
                Source = bitmapSource
            };
            windows_middle.Children.Add(image);
        }

        private void three_demo_draw(object sender, RoutedEventArgs e)
        {
            int img_width = 400;
            int img_height = 400;
            byte[] bytes = new byte[img_width * img_height];
            int k = 0;
            for (int i = 0; i < img_width; i++)
            {
                for (int j = 0; j < img_height; j++)
                {
                    bytes[k++] = (byte)((double)(i * j) / (img_width * img_height) * 255);
                }
            }
            Bitmap bmp = ToGrayBitmap(bytes, img_width, img_height);

            //bmp.Save(@"d:\test.png",System.Drawing.Imaging.ImageFormat.Png);
            IntPtr ip = bmp.GetHbitmap();//从GDI+ Bitmap创建GDI位图对象

            BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

            System.Windows.Controls.Image image = new System.Windows.Controls.Image
            {
                Width = img_width,
                Height = img_height,
                Name = "imgOutput",
                Source = bitmapSource
            };
            windows_middle.Children.Add(image);
        }

        public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
        {
            //申请目标位图的变量，并将其内存区域锁定
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
            ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);

            //获取图像参数
            int stride = bmpData.Stride;  // 扫描线的宽度  
            int offset = stride - width;  // 显示宽度与扫描线宽度的间隙  
            IntPtr iptr = bmpData.Scan0;  // 获取bmpData的内存起始位置  
            int scanBytes = stride * height;// 用stride宽度，表示这是内存区域的大小  

            //下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
            int posScan = 0, posReal = 0;// 分别设置两个位置指针，指向源数组和目标数组  
            byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存  

            for (int x = 0; x < height; x++)
            {
                //下面的循环节是模拟行扫描
                for (int y = 0; y < width; y++)
                {
                    pixelValues[posScan++] = rawValues[posReal++];
                }
                posScan += offset;  //行扫描结束，要将目标位置指针移过那段“间隙”  
            }

            //用Marshal的Copy方法，将刚才得到的内存字节数组复制到BitmapData中
            System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
            bmp.UnlockBits(bmpData);  // 解锁内存区域  

            //下面的代码是为了修改生成位图的索引表，从伪彩修改为灰度
            ColorPalette tempPalette;
            using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                tempPalette = tempBmp.Palette;
            }
            for (int i = 0; i <= 64; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb(0, (int)(255*i/64), 255);
            }
            for (int i = 65; i <= 128; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb(0, 255, 255 - (int)(255 * (i - 64) / 64));
            }
            for (int i = 129; i < 192; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb((int)(255 * (i-128) / 64), 255, 0);
            }
            for (int i = 192; i < 256; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb(255, (255 - i) * 255 / 64, 0);
            }

            bmp.Palette = tempPalette;

            //算法到此结束，返回结果
            return bmp;
        }
        //opencv示例
        private void drawqww()
        {
            Mat mat = new Mat("02.jpg", ImreadModes.Unchanged);
            //for (int y = 0; y < mat.Height; y++)
            //{
            //    for (int x = 0; x < mat.Width; x++)
            //    {
            //        Vec3b color = mat.Get<Vec3b>(y, x);
            //        byte temp = color.Item0;
            //        color.Item0 = color.Item2; //B 转 R
            //        color.Item2 = temp;        //R 转 B
            //        mat.Set(y, x, color);
            //    }
            //}
            MemoryStream mem = mat.ToMemoryStream();
            BitmapImage bmp = new BitmapImage();
            bmp.BeginInit();
            bmp.StreamSource = mem;
            bmp.EndInit();
            {
                System.Windows.Controls.Image image = new System.Windows.Controls.Image
                {
                    Height = 800,
                    Width = 400,
                    Name = "imgOutput",
                    Source = bmp
                };
                windows_middle.Children.Add(image);
            }
            mat.Dispose();/// 该方法在mat里被重写了，可以释放资源，可以放心调用
        }

        private void draw_131P(object sender, RoutedEventArgs e)
        {
            #region 数据准备
            {
                first_param.Text = value1.Value.ToString();
                second_param.Text = value2.Value.ToString();
                windows_middle.Children.Clear();
                #region 数据准备
                {
                    //定义文件路径
                    string filename = "CSES_01_EFD_3_L02_A1_066780_20190417_131231_20190417_134705_000.h5";
                    //新建dataset
                    GetHdf5DataSet getData = new GetHdf5DataSet();
                    //获取目录数组
                    string[] groupNames = getData.hdf5_getData(filename);
                    //只读模式打开
                    H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDWR);
                    //取其中某一目录
                    H5DataSetId dataSetId = H5D.open(fileId, groupNames[0]);
                    //获取目录的spaceid
                    H5DataSpaceId h5DataSpaceId = H5D.getSpace(dataSetId);
                    //查询目录在h5位置
                    int rank = H5S.getSimpleExtentNDims(h5DataSpaceId);
                    //查询目录矩阵大小
                    long[] a = H5S.getSimpleExtentDims(h5DataSpaceId);
                    //建立对应大数组
                    double[,] readDataBack = new double[a[0], a[1]];
                    //目录数据存入内存
                    H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE), new H5Array<double>(readDataBack));

                    #region 数据格式转化
                    byte[] readData_to_byte = new byte[a[0] * a[1]];
                    int readData_num = 0;
                    for (int i = 0; i < a[1]; i++)
                    {
                        for (int j = 0; j < a[0]; j++)
                        {
                            //电场算法        
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 8) * 22.5);
                            //readData_to_byte[readData_num++] = (byte)(12.5*(Math.Log(readDataBack[j, a[1] - 1 - i], 10)+15));
                            //磁场算法 
                            double value =90 * (Math.Log(readDataBack[j, a[1] - 1 - i], 10)) + 420;
                            if (value < 0)
                                value = 0;
                            if (value > 255)
                                value = 255;
                            readData_to_byte[readData_num++] = (byte)(value);
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 20) * 30);
                        }
                    }
                    #endregion
                    #region 画图
                    {
                        int img_width = (int)a[0];
                        int img_height = (int)a[1];

                        Bitmap bmp = ToGrayBitmap(readData_to_byte, img_width, img_height);

                        bmp.Save(@"d:\test.png", System.Drawing.Imaging.ImageFormat.Png);
                        IntPtr ip = bmp.GetHbitmap();//从GDI+ Bitmap创建GDI位图对象

                        BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

                        System.Windows.Controls.Image image = new System.Windows.Controls.Image
                        {
                            Width = img_width,
                            Height = img_height,
                            Name = "imgOutput",
                            Source = bitmapSource
                        };
                        windows_middle.Children.Add(image);
                    }
                    #endregion
                }
                #endregion
            }
            #endregion

        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            start = 1;
            
        }

        private void Value1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (start == 1 && public_readData_to_byte != null)
            {
                first_param.Text = value1.Value.ToString();
                second_param.Text = value2.Value.ToString();
                windows_middle.Children.Clear();
                #region 数据准备
                {
                    //定义文件路径
                    string filename = "CSES_01_SCM_3_L02_A2_064560_20190402_224035_20190402_231601_000.h5";
                    //新建dataset
                    GetHdf5DataSet getData = new GetHdf5DataSet();
                    //获取目录数组
                    string[] groupNames = getData.hdf5_getData(filename);
                    //只读模式打开
                    H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDWR);
                    //取其中某一目录
                    H5DataSetId dataSetId = H5D.open(fileId, groupNames[0]);
                    //获取目录的spaceid
                    H5DataSpaceId h5DataSpaceId = H5D.getSpace(dataSetId);
                    //查询目录在h5位置
                    int rank = H5S.getSimpleExtentNDims(h5DataSpaceId);
                    //查询目录矩阵大小
                    long[] a = H5S.getSimpleExtentDims(h5DataSpaceId);
                    //建立对应大数组
                    double[,] readDataBack = new double[a[0], a[1]];
                   #region 数据格式转化
                    byte[] readData_to_byte = new byte[a[0] * a[1]];
                    int readData_num = 0;
                    for (int i = 0; i < a[1]; i++)
                    {
                        for (int j = 0; j < a[0]; j++)
                        {
                            //电场算法        
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 8) * 22.5);
                            //readData_to_byte[readData_num++] = (byte)(12.5*(Math.Log(readDataBack[j, a[1] - 1 - i], 10)+15));
                            //磁场算法 
                            double value = Convert.ToInt32(value1.Value) * (Math.Log(public_readData_to_byte[j, a[1] - 1 - i], 10)) + Convert.ToInt32(value2.Value);
                            if (value < 0)
                                value = 0;
                            if (value > 255)
                                value = 255;
                            readData_to_byte[readData_num++] = (byte)(value);
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 20) * 30);
                        }
                    }
                    #endregion
                    #region 画图
                    {
                        int img_width = (int)a[0];
                        int img_height = (int)a[1];

                        Bitmap bmp = ToGrayBitmap(readData_to_byte, img_width, img_height);

                        bmp.Save(@"d:\test.png", System.Drawing.Imaging.ImageFormat.Png);
                        IntPtr ip = bmp.GetHbitmap();//从GDI+ Bitmap创建GDI位图对象

                        BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

                        System.Windows.Controls.Image image = new System.Windows.Controls.Image
                        {
                            Width = img_width/3,
                            Height = img_height/3,
                            Name = "imgOutput",
                            Source = bitmapSource
                        };
                        windows_middle.Children.Add(image);
                    }
                    #endregion
                }
                #endregion
            }
        }

        private void draw_131P_magnetic_field(object sender, RoutedEventArgs e)
        {
            #region 数据准备
            {
                first_param.Text = value1.Value.ToString();
                second_param.Text = value2.Value.ToString();
                windows_middle.Children.Clear();
                #region 数据准备
                {
                    //定义文件路径
                    string filename = "CSES_01_SCM_3_L02_A2_064560_20190402_224035_20190402_231601_000.h5";
                    //新建dataset
                    GetHdf5DataSet getData = new GetHdf5DataSet();
                    //获取目录数组
                    string[] groupNames = getData.hdf5_getData(filename);
                    //只读模式打开
                    H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDWR);
                    //取其中某一目录
                    H5DataSetId dataSetId = H5D.open(fileId, groupNames[0]);
                    //获取目录的spaceid
                    H5DataSpaceId h5DataSpaceId = H5D.getSpace(dataSetId);
                    //查询目录在h5位置
                    int rank = H5S.getSimpleExtentNDims(h5DataSpaceId);
                    //查询目录矩阵大小
                    long[] a = H5S.getSimpleExtentDims(h5DataSpaceId);
                    //建立对应大数组
                    double[,] readDataBack = new double[a[0], a[1]];
                    //目录数据存入内存
                    H5D.read(dataSetId, new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE), new H5Array<double>(readDataBack));

                    #region 数据格式转化
                    byte[] readData_to_byte = new byte[a[0] * a[1]];
                    public_readData_to_byte = readDataBack;
                    int readData_num = 0;
                    for (int i = 0; i < a[1]; i++)
                    {
                        for (int j = 0; j < a[0]; j++)
                        {
                            //电场算法        
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 8) * 22.5);
                            //readData_to_byte[readData_num++] = (byte)(12.5*(Math.Log(readDataBack[j, a[1] - 1 - i], 10)+15));
                            //磁场算法 
                            double value = 90 * (Math.Log(readDataBack[j, a[1] - 1 - i], 10)) + 420;
                            if (value < 0)
                                value = 0;
                            if (value > 255)
                                value = 255;
                            readData_to_byte[readData_num++] = (byte)(value);
                            //readData_to_byte[readData_num++] = (byte)((Math.Log(readDataBack[j, a[1]-1-i], 10) + 20) * 30);
                        }
                    }
                    #endregion
                    #region 画图
                    {
                        int img_width = (int)a[0];
                        int img_height = (int)a[1];

                        Bitmap bmp = ToGrayBitmap(readData_to_byte, img_width, img_height);

                        bmp.Save(@"d:\test.png", System.Drawing.Imaging.ImageFormat.Png);
                        IntPtr ip = bmp.GetHbitmap();//从GDI+ Bitmap创建GDI位图对象

                        BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

                        System.Windows.Controls.Image image = new System.Windows.Controls.Image
                        {
                            Width = img_width,
                            Height = img_height,
                            Name = "imgOutput",
                            Source = bitmapSource
                        };
                        windows_middle.Children.Add(image);
                    }
                    #endregion
                }
                #endregion
            }
            #endregion
        }
    }
}
